package com.maxjay.component.metadata.service.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.maxjay.component.metadata.constant.GeneratorEnableType;
import com.maxjay.component.metadata.core.interceptor.EntityInterceptor;
import com.maxjay.component.metadata.model.Entity;
import com.maxjay.component.metadata.model.EntityField;
import com.maxjay.component.metadata.model.Record;
import com.maxjay.component.metadata.service.EntityService;
import com.maxjay.system.service.BaseServiceJdbc;

@Service("entityService")
@Transactional
public class EntityServiceImpl extends BaseServiceJdbc implements EntityService {
	
	private static Logger LOG = Logger.getLogger(EntityServiceImpl.class);
	
	@Override
	public Record load(Entity entity, String entityObjId) {
		StringBuilder sb = new StringBuilder();
		sb.append("SELECT ");
		int i = 1;
		List<EntityField> fieldList = entity.getEntityFields();
		for (EntityField entityField : fieldList) {
			if (entityField.isVirtual()) {
				continue;
			}
			sb.append(entityField.getName());
			if (i < fieldList.size()) {
				sb.append(",");
			}
			i++;
		}
		sb.append(" FROM ").append(entity.getTabName()).append(" WHERE OBJ_ID=? ");
		LOG.debug("实体对象的查询SQL为：" + sb.toString() + "，实体对象ID为：" + entityObjId);
		Map<String, Object> dataMap = this.getSimpleJdbcTemplate().queryForMap(sb.toString(), entityObjId);
		Record storeRecord = new Record(dataMap);
		return storeRecord;
	}
	
	@Override
	public Record loadDisplay(Entity entity, String entityObjId) {
		Record storeRecord = load(entity, entityObjId);
		return convertDisplay(entity, storeRecord);
	}
	
	/**
	 * 转换为数据库可存储的Map
	 * 
	 * @param entity
	 * @param record
	 * @return
	 */
	protected Record convertDisplay(Entity entity, Record storeRecord) {
		Map<String, Object> displayMap = new HashMap<String, Object>();
		for (Map.Entry<String, Object> dataEntry : storeRecord.getDataMap().entrySet()) {
			EntityField entityField = entity.getEntityFieldByName(dataEntry.getKey());
			displayMap.put(dataEntry.getKey(), entityField.convertDisplayValue(storeRecord));
		}
		LOG.debug("转换后的显示数据为：" + displayMap);
		return new Record(displayMap);
	}
	

	@Override
	public void save(Entity entity, List<Record> records) {
		for (Record record : records) {
			this.save(entity, record);
		}
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED)
	public void save(Entity entity, Record record) {
		// 执行数据插入前的拦截操作
		for (EntityInterceptor entityInterceptor : entity.getEntityInterceptors()) {
			entityInterceptor.beforeCreate(entity, record);
		}
		
		// 执行插入操作
		StringBuilder sb = new StringBuilder();
		StringBuilder fieldSb = new StringBuilder();
		StringBuilder valueSb = new StringBuilder();
		String tabName = entity.getTabName();
		sb.append("insert into ").append(tabName).append("(");
		for(EntityField field : entity.getEntityFields()) {
			if (field.isVirtual()) {
				continue;
			}
			String fieldName = field.getName();
			if (record.containsField(fieldName)) {
				fieldSb.append(fieldName).append(",");
				valueSb.append(":").append(fieldName).append(",");
				if (StringUtils.isBlank((String)record.getValue(fieldName)) && field.getValueGenerator() != null 
						&& GeneratorEnableType.onSave == field.getValueGenerator().getEnableType()) {
					record.setValue(fieldName, field.getValueGenerator().generateValue(entity, record));
				}
			} else {
				if (field.getValueGenerator() != null) {
					fieldSb.append(fieldName).append(",");
					valueSb.append(":").append(fieldName).append(",");
					record.setValue(fieldName, field.getValueGenerator().generateValue(entity, record));
				}
			}
		}
		sb.append(fieldSb.subSequence(0, fieldSb.length()-1)).append(") values (")
			.append(valueSb.subSequence(0, valueSb.length()-1)).append(")");
		LOG.debug("实体新增SQL为：" + sb.toString());
		this.getSimpleJdbcTemplate().update(sb.toString(), convertStoreParams(entity, record));
		
		// 执行插入后的拦截操作
		for (EntityInterceptor entityInterceptor : entity.getEntityInterceptors()) {
			entityInterceptor.afterCreate(entity, record);
		}
	}

	@Override
	public void update(Entity entity, List<Record> records) {
		for (Record record : records) {
			this.update(entity, record);
		}
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED)
	public void update(Entity entity, Record record) {
		// 执行数据更新前的拦截操作
		for (EntityInterceptor entityInterceptor : entity.getEntityInterceptors()) {
			entityInterceptor.beforeUpdate(entity, record);
		}
		
		// 执行数据更新操作
		StringBuilder sb = new StringBuilder();
		StringBuilder fieldValueSb = new StringBuilder();
		String tabName = entity.getTabName();
		sb.append("update ").append(tabName).append(" set ");
		for(EntityField field : entity.getEntityFields()) {
			if (field.isVirtual()) {
				continue;
			}
			String fieldName = field.getName();
			if (record.containsField(fieldName)) {
				fieldValueSb.append(fieldName).append("=:").append(fieldName).append(",");
			}
		}
		String keyFieldName = entity.getKeyField().getName();
		if(record.getValue(keyFieldName) == null) {
			throw new RuntimeException("实体[" + tabName + "]的主键[" + keyFieldName + "]为空，无法执行更新操作");
		}
		sb.append(fieldValueSb.substring(0, fieldValueSb.length() - 1)).append(" where ").append(keyFieldName)
				.append("=:").append(keyFieldName);
		LOG.debug("实体更新SQL为：" + sb.toString());
		this.getSimpleJdbcTemplate().update(sb.toString(), convertStoreParams(entity, record));
		
		// 执行数据更新后的拦截操作
		for (EntityInterceptor entityInterceptor : entity.getEntityInterceptors()) {
			entityInterceptor.afterUpdate(entity, record);
		}
	}
	

	@Override
	public void delete(Entity entity, List<String> keyFieldValues) {
		for (String keyFieldValue : keyFieldValues) {
			this.delete(entity, keyFieldValue);
		}
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED)
	public void delete(Entity entity, String keyFieldValue) {
		// 执行数据更新前的拦截操作
		for (EntityInterceptor entityInterceptor : entity.getEntityInterceptors()) {
			entityInterceptor.beforeDelete(entity, keyFieldValue);
		}
		
		// 执行删除操作
		StringBuilder sb = new StringBuilder();
		String keyFieldName = entity.getKeyField().getName();
		if(StringUtils.isBlank(keyFieldValue)) {
			throw new RuntimeException("实体[" + entity.getTabName() + "]的主键[" + keyFieldName + "]为空，无法执行更新操作");
		}
		sb.append("delete from ").append(entity.getName()).append(" where ").append(keyFieldName).append("=? ");
		LOG.debug("实体删除SQL为：" + sb.toString());
		LOG.debug("实体对象ID为：" + keyFieldValue);
		this.getSimpleJdbcTemplate().update(sb.toString(), keyFieldValue);
		
		// 执行数据更新后的拦截操作
		for (EntityInterceptor entityInterceptor : entity.getEntityInterceptors()) {
			entityInterceptor.afterDelete(entity, keyFieldValue);
		}
	}

	/**
	 * 转换为数据库可存储的Map
	 * 
	 * @param entity
	 * @param record
	 * @return
	 */
	protected Map<String, Object> convertStoreParams(Entity entity, Record record) {
		Map<String, Object> params = new HashMap<String, Object>();
		for (Map.Entry<String, Object> dataEntry : record.getDataMap().entrySet()) {
			EntityField entityField = entity.getEntityFieldByName(dataEntry.getKey());
			params.put(dataEntry.getKey(), entityField.convertStoreValue(record));
		}
		LOG.debug("转换后的数据库存储参数为：" + params);
		return params;
	}

}
